﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using Random = System.Random;
using Newtonsoft.Json.Linq;

public class Util
{
    public static int Int(object o)
    {
        return Convert.ToInt32(o);
    }

    public static bool Bool(object o)
    {
        return Convert.ToBoolean(o);
    }

    public static float Float(object o)
    {
        return (float) Math.Round(Convert.ToSingle(o), 2);
    }

    public static long Long(object o)
    {
        return Convert.ToInt64(o);
    }

    public static int Random(int min, int max)
    {
        return UnityEngine.Random.Range(min, max);
    }

    public static float Random(float min, float max)
    {
        return UnityEngine.Random.Range(min, max);
    }

    public static int ColorToInt(Color32 color)
    {
        return color.r * 65536 + color.g * 256 + color.b;
    }

    public static long GetTime()
    {
        TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks);
        return (long) ts.TotalMilliseconds;
    }

    /// <summary>
    /// 查找子对象
    /// </summary>
    public static GameObject Child(GameObject go, string subnode)
    {
        return Child(go.transform, subnode);
    }

    /// <summary>
    /// 查找子对象
    /// </summary>
    public static GameObject Child(Transform go, string subnode)
    {
        Transform tran = go.Find(subnode);
        if (tran == null) return null;
        return tran.gameObject;
    }

    /// <summary>
    /// 取平级对象
    /// </summary>
    public static GameObject Peer(GameObject go, string subnode)
    {
        return Peer(go.transform, subnode);
    }

    /// <summary>
    /// 取平级对象
    /// </summary>
    public static GameObject Peer(Transform go, string subnode)
    {
        Transform tran = go.parent.Find(subnode);
        if (tran == null) return null;
        return tran.gameObject;
    }

    /// <summary>
    /// 计算字符串的MD5值
    /// </summary>
    public static string md5(string source)
    {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
        byte[] data = Encoding.UTF8.GetBytes(source);
        byte[] md5Data = md5.ComputeHash(data, 0, data.Length);
        md5.Clear();

        string destString = "";
        for (int i = 0; i < md5Data.Length; i++)
        {
            destString += Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
        }

        destString = destString.PadLeft(32, '0');
        return destString;
    }

    /// <summary>
    /// 计算文件的MD5值
    /// </summary>
    public static string md5file(string file)
    {
        try
        {
            FileStream fs = new FileStream(file, FileMode.Open);
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(fs);
            fs.Close();

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }

            return sb.ToString();
        }
        catch (Exception ex)
        {
            throw new Exception("md5file() fail, error:" + ex.Message);
        }
    }

    /// <summary>
    /// 清除所有子节点
    /// </summary>
    public static void ClearChild(Transform go)
    {
        if (go == null) return;
        for (int i = go.childCount - 1; i >= 0; i--)
        {
            GameObject.Destroy(go.GetChild(i).gameObject);
        }
    }

    /// <summary>
    /// 清理内存
    /// </summary>
    public static void ClearMemory()
    {
        GC.Collect();
        Resources.UnloadUnusedAssets();
    }

    /// <summary>
    /// 取得行文本
    /// </summary>
    public static string GetFileText(string path)
    {
        return File.ReadAllText(path);
    }

    /// <summary>
    /// 向文件写入内容，不覆盖
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="content"></param>
    public static void WriteToFile(string filePath, string content)
    {
        string fullPath = Path.GetDirectoryName(filePath);
        if (!Directory.Exists(fullPath))
            Directory.CreateDirectory(fullPath);

        if (!File.Exists(filePath))
        {
            FileStream fileStream = File.Create(filePath);
            fileStream.Close();
        }

        FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
        StreamWriter m_streamWriter = new StreamWriter(fs);
        m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
        m_streamWriter.WriteLine(content);
        m_streamWriter.Flush();
        m_streamWriter.Close();
    }

    /// <summary>
    /// 异步向文件写入，会覆盖原有的内容
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="content"></param>
    /// <param name="finishCallback"></param>
    public static async void WriteToFileAsync(string filePath, string content, Action finishCallback)
    {
        string fullPath = Path.GetDirectoryName(filePath);
        if (!Directory.Exists(fullPath))
            Directory.CreateDirectory(fullPath);

        StreamWriter sw = new StreamWriter(filePath);
        await sw.WriteAsync(content);
        await sw.FlushAsync();
        sw.Close();
        sw.Dispose();
        finishCallback?.Invoke();
    }

    /// <summary>
    /// 同步向文件写入内容，会覆盖原来的内容
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="content"></param>
    public static void WriteToFileCover(string filePath, string content)
    {
        string fullPath = Path.GetDirectoryName(filePath);
        if (!Directory.Exists(fullPath))
            Directory.CreateDirectory(fullPath);

        StreamWriter sw = new StreamWriter(filePath);
        sw.Write(content);
        sw.Flush();
        sw.Close();
    }


    /// <summary>
    /// 网络可用
    /// </summary>
    public static bool NetAvailable
    {
        get { return Application.internetReachability != NetworkReachability.NotReachable; }
    }

    /// <summary>
    /// 是否是无线
    /// </summary>
    public static bool IsWifi
    {
        get { return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork; }
    }

    /// <summary>
    /// 清空文件夹下文件
    /// </summary>
    /// <param name="path"></param>
    public static void DeleteFolder(string path)
    {
        foreach (string d in Directory.GetFileSystemEntries(path))
        {
            if (File.Exists(d))
            {
                FileInfo fi = new FileInfo(d);
                if (fi.Attributes.ToString().IndexOf("ReadOnly") != -1)
                    fi.Attributes = FileAttributes.Normal;
                File.Delete(d); //直接删除其中的文件  
            }
            else
            {
                DirectoryInfo d1 = new DirectoryInfo(d);
                if (d1.GetFiles().Length != 0)
                {
                    DeleteFolder(d1.FullName); ////递归删除子文件夹
                }

                Directory.Delete(d);
            }
        }
    }


    /// <summary>
    /// 克隆一个对象
    /// </summary>
    /// <param name="sampleObject"></param>
    /// <returns></returns>
    public static object CloneObject(object sampleObject)
    {
        Type t = sampleObject.GetType();
        PropertyInfo[] propertyInfos = t.GetProperties();
        object p = t.InvokeMember("", BindingFlags.CreateInstance, null, sampleObject, null);
        foreach (PropertyInfo propertyInfo in propertyInfos)
        {
            if (propertyInfo.CanWrite)
            {
                object value = propertyInfo.GetValue(sampleObject, null);
                propertyInfo.SetValue(p, value, null);
            }
        }

        return p;
    }

    /// <summary>
    /// 时间格式化（与服务器时间格式匹配）
    /// </summary>
    /// <param name="nDate"></param>
    /// <returns></returns>
    public static string DateTimeFormat(DateTime nDate)
    {
        return nDate.ToString("yyyy-MM-dd HH:mm:ss");
    }

    /// <summary>
    /// 将秒数格式化为h时m分s秒的格式
    /// </summary>
    /// <param name="second"></param>
    /// <returns></returns>
    public static string SecondFormatHMS(int second)
    {
        TimeSpan ts = new TimeSpan(0, 0, second);
        if (second < 60)
        {
            return ts.Seconds + "秒";
        }
        else if (second < 3600)
        {
            return $"{ts.Minutes}分{ts.Seconds}秒";
        }
        else if (second < 86400)
        {
            return $"{ts.Hours}时{ts.Minutes}分{ts.Seconds}秒";
        }
        else
        {
            return $"{ts.Days}天{ts.Hours}时{ts.Minutes}分{ts.Seconds}秒";
        }
    }

    /// <summary>
    /// base64编码文本转换成Sprite
    /// </summary>
    /// <param name="nBase64String"></param>
    /// <returns></returns>
    public static Sprite Base64ToSprite(string nBase64String)
    {
        if (string.IsNullOrEmpty(nBase64String))
            return null;

        try
        {
            byte[] bytes = Convert.FromBase64String(nBase64String);
            Texture2D tex2D = new Texture2D(256, 256);
            tex2D.LoadImage(bytes);
            Sprite sprite = Sprite.Create(tex2D, new Rect(0, 0, tex2D.width, tex2D.height), new Vector2(0.5f, 0.5f));
            return sprite;
        }
        catch (Exception e)
        {
            Debug.Log("FromBase64String编译出错！ e:" + e);
            return null;
        }
    }

    /// <summary>
    /// 生成随机数数组
    /// </summary>
    /// <param name="length">生成的个数</param>
    /// <param name="max">随机数取值最大值</param>
    /// <returns></returns>
    public static int[] GenerateRandom(int length, int max)
    {
        if (length <= 0 || max <= 0)
            return null;

        int[] result = new int[length];
        for (int i = 0; i < length; i++)
        {
            var r = new Random(Guid.NewGuid().GetHashCode());
            result[i] = r.Next(0, max);
        }

        return result;
    }

    /// <summary>
    /// 当前是否在移动端
    /// </summary>
    /// <returns></returns>
    public static bool IsAndroid()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
    return true;
#elif UNITY_IOS && !UNITY_EDITOR
    return true;
#endif
        return false;
    }

    /// <summary>
    /// 验证是否为手机号码
    /// </summary>
    /// <param name="str_handset"></param>
    /// <returns></returns>
    public static bool IsHandset(string str_handset)
    {
        return System.Text.RegularExpressions.Regex.IsMatch(str_handset, @"^1[3456789]\d{9}$");
    }

    /// <summary>
    /// 请list中最大的绝对值
    /// </summary>
    /// <returns></returns>
    public static float MaxAbs(List<int> list)
    {
        float max = list.Max();
        float min = list.Min();
        float Abs_minValue = Math.Abs(min);
        if (Abs_minValue > max)
        {
            return Abs_minValue;
        }
        else
        {
            return max;
        }
    }

    /// <summary>
    /// 垂直翻转Texture
    /// </summary>
    public static Texture2D VerticalFlipTexture(Texture2D texture)
    {
        int width = texture.width;
        int height = texture.height;
        Texture2D flipTexture = new Texture2D(width, height);
        for (int i = 0; i < height; i++)
        {
            flipTexture.SetPixels(0, i, width, 1, texture.GetPixels(0, height - i - 1, width, 1));
        }

        flipTexture.Apply();
        return flipTexture;
    }

    /// <summary>
    /// 水平翻转Texture
    /// </summary>
    public static Texture2D HorizontalFlipTexture(Texture2D texture)
    {
        int width = texture.width;
        int height = texture.height;
        Texture2D flipTexture = new Texture2D(width, height);
        for (int i = 0; i < width; i++)
        {
            flipTexture.SetPixels(i, 0, 1, height, texture.GetPixels(width - i - 1, 0, 1, height));
        }

        flipTexture.Apply();
        return flipTexture;
    }

    /// <summary>
    /// 获取游戏配置
    /// </summary>
    /// <param name="configName">游戏配置名(无需后缀名)</param>
    /// <returns></returns>
    public static JObject GetConfig(string configName)
    {
        return Global.GameConfigMgrIns.GetConfig(configName);
    }

    public static void ShowWaitLoading(Action action)
    {
        Debug.LogWarning("待补充：ShowWaitLoading");
    }

    public static void HideWaitLoading()
    {
        Debug.LogWarning("待补充：HideWaitLoading");
    }

    public static void ShowTips(string msgInfo)
    {
        Debug.LogWarning("待补充：ShowTips");
    }
}